using System;
using System.Collections.Generic;
using MazeBuilder.Entities;
using MazeBuilder.Entities.Tiles;
using RoomModuleCatalog;

namespace MazeBuilder
{
  public abstract class Digger
  {
    public event RoomBuilded oneBuilded;

    public void OnOneBuilded(RoomBuildedArgs args)
    {
      var handler = oneBuilded;
      if (handler != null) handler(this, args);
    }

    public event builded builded;

    public void OnBuilded(buildedArgs args) {
      var handler = builded;
      if (handler != null) handler(this, args);
    }

    public enum Direction
    {
      None = 0,
      North,
      East,
      South,
      West
    }

    public enum Mode
    {
      Standard,
      Uniform
    }
    
    public abstract void Build(Maze maze);

    public virtual void DigRoom(Maze maze, Tile tile)
    {
    }

    protected virtual void manageBounders(Maze maze, Dictionary<Direction, bool> bounders, int i, int j, int startRow, int startCol)
    {
      
    }

    protected static Dictionary<Direction, bool> getBounders(Tile tile, Maze maze) {
      var result = new Dictionary<Direction, bool>();
      var c = maze._configuration;
      var tt = maze.tiles;
      var t = tile;
      try {
        result.Add(Direction.North, tt[t.Row - (c.RoomHeight) - 1][t.Col] != null && !(tt[t.Row - (c.RoomHeight) - 1][t.Col] is NullTile));
        result.Add(Direction.East, tt[t.Row][t.Col + (c.RoomWidth) + 1] != null && !(tt[t.Row - (c.RoomHeight) - 1][t.Col] is NullTile));
        result.Add(Direction.South, tt[t.Row + (c.RoomHeight) + 1][t.Col] != null && !(tt[t.Row - (c.RoomHeight) - 1][t.Col] is NullTile));
        result.Add(Direction.West, tt[t.Row][t.Col - (c.RoomWidth) - 1] != null && !(tt[t.Row - (c.RoomHeight) - 1][t.Col] is NullTile));
      }
      catch (Exception exception) {
        Console.WriteLine(exception);
      }
      return result;
    }
  }

  public delegate void builded(object sender, buildedArgs args);

  public class buildedArgs
  {
  }

  public delegate void RoomBuilded(object sender, RoomBuildedArgs args);

  public class RoomBuildedArgs
  {
  }

  public class DiggerFactory
  {
    private static Digger instance = null;

    public static Digger GetDigger(IMazeConfiguration configuration)
    {
      Digger result = null;
      switch (configuration.DiggerMode)
      {
          case (int)Digger.Mode.Standard:
          result = instance ?? (instance = new StandardDigger());
          break;
          case (int)Digger.Mode.Uniform:
          result = instance ?? (instance = new UniformDigger());
          break;
      }
      return result;
    }
  }
}